package com.seestech.sell.common.interceptor;

import com.seestech.sell.common.annotation.Duplicate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.Arrays;
import java.util.Comparator;
import java.util.TreeMap;

/**
 * Created by idiot on 2017/5/31.
 * @description       防止重复提交拦截器
 */
public class DuplicateInterceptor implements HandlerInterceptor {

    private static Logger logger = LoggerFactory.getLogger(DuplicateInterceptor.class);

    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
        HttpSession session = httpServletRequest.getSession();
        //  获取防止重复提交的注解
        HandlerMethod handlerMethod = (HandlerMethod) o;
        Duplicate duplicate = handlerMethod.getMethodAnnotation(Duplicate.class);
        //  判断是否为空   以及value是否为true
        if(duplicate != null && duplicate.value()){
            logger.info("重复提交检测开始============>>>>>>>>>>>>>>>>>>");
            //  获取request中请求的url以及携带的参数 获取hashcode  与上一次存入session的hashcode 比较
            Integer currentCode = new HandleParameter(httpServletRequest).toString().hashCode();
            Integer oldCode = (Integer) session.getAttribute("old_code");
            Long currentTime = System.currentTimeMillis();
            Long oldTime = (Long) session.getAttribute("old_time");
            session.setAttribute("old_code", currentCode);
            session.setAttribute("old_time", currentTime);
            // logger.info("============>>>>>>>>>>>>>>>>>>currentCode:"+currentCode+"====oldcode:"+oldCode+"\n===currentTime:"+currentTime+"===oldTime:"+oldTime);
            if(oldCode != null && oldTime != null && currentCode.equals(oldCode) && ((currentTime - oldTime) <= 1000) ){
                logger.error("=============>>>>>>>>【判定为重复提交】============>>>>>");
                httpServletResponse.getWriter().write("<script type='text/javascript'>layer.msg('系统繁忙，请稍后再试', {icon:5,time:1000})</script>");
                return false;
            }
        }
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {

    }

    /**
     * 参数处理
     * Created by Hong on 2017/5/26.
     */
    class HandleParameter {

        private java.util.Map<String, String> map = null;

        public HandleParameter(HttpServletRequest request) {

            //构造Tree有序Map
            map = new TreeMap<>(new Comparator<String>() {
                @Override
                public int compare(String o1, String o2) {
                    return o1.compareTo(o2);
                }
            });

            //添加请求路径参数
            map.put("path", request.getRequestURI());

            init(request);
        }

        /**
         * 组装参数
         */
        private void init(HttpServletRequest request) {
            java.util.Map<String, String[]> params = request.getParameterMap();
            for (String key : params.keySet()) {
                map.put(key, convert(params.get(key)));
            }
        }

        /**
         * 数组参数转换
         */
        private String convert(String[] strs) {
            Arrays.sort(strs);
            StringBuilder builder = new StringBuilder();
            for (String str : strs) {
                builder.append(str);
            }
            return builder.toString();
        }

        @Override
        public String toString() {
            StringBuilder builder = new StringBuilder();
            for (String key : map.keySet()) {
                builder.append("," + key + "=" + map.get(key));
            }
            builder.deleteCharAt(0);
            return builder.toString();
        }
    }
}
